import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 设置 Matplotlib 中文支持
plt.rcParams["font.sans-serif"] = ["SimHei"]  # 使用黑体
plt.rcParams["axes.unicode_minus"] = False   # 解决负号问题

# ========== 1️⃣  读取四个表格数据 ==========
# 订单数据（近三年）
orders_2023 = pd.read_csv("orders_2023.csv")
orders_2022 = pd.read_csv("orders_2022.csv")
orders_2021 = pd.read_csv("orders_2021.csv")

# 会员信息
members = pd.read_csv("members.csv")

# 合并近三年的订单数据
orders = pd.concat([orders_2021, orders_2022, orders_2023], ignore_index=True)

# ========== 2️⃣  数据预处理 ==========
orders = orders[["会员ID", "订单日期", "消费金额"]].dropna()  # 去除缺失值
orders["订单日期"] = pd.to_datetime(orders["订单日期"])  # 转换日期格式

# 计算分析基准日期（假设是最近一天）
analysis_date = orders["订单日期"].max()

# ========== 3️⃣  计算 RFM 值 ==========
rfm = orders.groupby("会员ID").agg({
    "订单日期": lambda x: (analysis_date - x.max()).days,  # R：最近一次消费天数
    "会员ID": "count",  # F：消费次数
    "消费金额": "sum"   # M：消费总额
}).rename(columns={"订单日期": "最近消费（天）", "会员ID": "消费频率", "消费金额": "消费总额"})

# ========== 4️⃣  合并 RFM 数据到会员表 ==========
rfm = rfm.reset_index()
rfm_data = pd.merge(members, rfm, on="会员ID", how="left").fillna(0)  # 未消费用户补 0

# ========== 5️⃣  使用 pd.qcut() 进行三等分 ==========
rfm_data["R_Score"] = pd.qcut(rfm_data["最近消费（天）"], q=3, labels=[2, 1, 0])  # 越小越活跃
rfm_data["F_Score"] = pd.qcut(rfm_data["消费频率"], q=3, labels=[0, 1, 2])  # 越大越忠诚
rfm_data["M_Score"] = pd.qcut(rfm_data["消费总额"], q=3, labels=[0, 1, 2])  # 越大消费越高

# ========== 6️⃣  绘制 3D 柱形图 ==========
fig = plt.figure(figsize=(10, 7))
ax = fig.add_subplot(111, projection="3d")

# 取出 RFM 分数
x = rfm_data["R_Score"].astype(int)
y = rfm_data["F_Score"].astype(int)
z = rfm_data["M_Score"].astype(int)

# 统计每个 (R, F, M) 组合出现的次数
hist, edges = np.histogramdd((x, y, z), bins=(3, 3, 3))

# 3D 柱形图的 X、Y、Z 坐标
xpos, ypos, zpos = np.meshgrid(np.arange(3), np.arange(3), np.arange(3), indexing="ij")
xpos = xpos.ravel()
ypos = ypos.ravel()
zpos = np.zeros_like(xpos)

# 柱形高度
dz = hist.ravel()

# 颜色映射
colors = plt.cm.viridis(dz / dz.max())

# 绘制柱形图
ax.bar3d(xpos, ypos, zpos, 0.5, 0.5, dz, color=colors, shade=True)

# 设置坐标轴标签（中文）
ax.set_xlabel("最近消费（R）")
ax.set_ylabel("消费频率（F）")
ax.set_zlabel("消费总额（M）")
ax.set_title("RFM 会员价值 3D 柱形图")

# 显示图像
plt.show()
